package com.freshmarket.freshmarket.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
@Slf4j
public class LogAspect {

    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    private void getMethod() {
    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
    private void postMethod() {
    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    private void allMethod() {
    }

    @Pointcut("getMethod() || postMethod() || allMethod()")
    public void logAspect() {
    }

    @Around("logAspect()")
    public Object logger(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            //记录开始时间
            long start = System.currentTimeMillis();
            //获取request对象
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            //通过request得到请求地址和请求来源IP
            String requestURI = request.getRequestURI();
            String remoteAddr = request.getRemoteAddr();
            //获取参数
            Object[] args = joinPoint.getArgs();
            //遍历携带的参数并log
            for (Object arg : args) {
                log.info("|---->请求者IP : {} |---->请求地址 : {} |---->传入值 : {}", remoteAddr, requestURI, arg);
            }
            //执行方法 报错后也log
            Object proceed = joinPoint.proceed(args);
            //结束后记录运行时长并log
            long end = System.currentTimeMillis();
            log.info("执行时长: {}", end - start);
            return proceed;
        } catch (Throwable throwable) {
            log.error("|---->错误 : {}", throwable.getMessage());
            throw throwable;
        }
    }
}
